import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_module/base/model/constants.dart';
import 'package:flutter_module/controller/web_controller.dart';
import 'package:flutter_module/util/log_u.dart';
import 'package:get/get.dart';
import 'package:webview_flutter/webview_flutter.dart';

///
///Flutter内嵌H5页面的方案。在合适的场景下，该技术能够帮助我们更好地利用各类资源，构建更加高效和优秀的移动应用。
///
/// https://www.jianshu.com/p/2a794e4e3f7b
/// Flutter与Js的交互
///
/// https://juejin.cn/post/7230644271950446650
/// JavascriptChannel：通过Javascript通信。
/// MethodChannel：通过建立Binder通道和Android原生代码通信。
/// JavascriptChannel在需求短时较为直观、实现相对简单，MethodChannel在处理较复杂的逻辑时，更加清晰明了。

/// Js向Flutter传递参数
/// 1.通过URL方式
/// 2.通过JavaScriptChannels方式
///
/// Flutter 向JS传递数据
/// 1.通过URL方式
/// 2.runJavaScript
class UWebView extends StatefulWidget {
  final Map<dynamic, dynamic> params; //获取flutter层传递过来的信息

  const UWebView({super.key, required this.params});

  @override
  State<UWebView> createState() => _UWebViewState();
}

class _UWebViewState extends State<UWebView> {
  String? url;
  final webController = Get.find<WebController>();
  late WebViewController _controller;

  @override
  void initState() {
    super.initState();
    url = widget.params[Constants.url];
    LogU.log('initState url =  $url');
    _initWebViewController();
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      //在当前页面即将被关闭之前否决关闭指令的组件
      canPop: false,
      //当 canPop 为 false，则系统返回手势不会将路由从封闭的 Navigator 中弹出，但仍然会调用 onPopInvoked(onPopInvokedWithResult) 方法
      onPopInvokedWithResult: (bool didPop, Object? result) async {
        if (didPop) {
          //这里的逻辑不能省略，原理暂时不了解；
          return;
        }
        if (await _controller.canGoBack()) {
          //返回H5的上一页
          _controller.goBack();
        } else {
          BoostNavigator.instance.pop();
        }
      },
      child: Scaffold(
        body: WebViewWidget(
          controller: _controller,
        ),
      ),
    );
  }

  void _initWebViewController() {
    //参考：webview_flutter使用详解
    ///https://blog.csdn.net/the_shy_faker/article/details/138174982
    _controller = WebViewController()
      //是否启用JavaScript执行，默认不启用
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..addJavaScriptChannel("customFunName",
          onMessageReceived: (JavaScriptMessage jsMessage) {
        var fromH5Message = jsMessage.message;
        LogU.log("来自H5传递过来的消息 $fromH5Message");
        // customFunName.postMessage("参数")  //h5端核心逻辑  customFunName需要跟addJavaScriptChannel中的第一个参数一致
      })
      //设置webview的背景色
      ..setBackgroundColor(const Color(0x00000000))
      //这里的 NavigationDecision.prevent表示阻止路由替换，NavigationDecision.navigate表示允许路由替换
      ..setNavigationDelegate(NavigationDelegate(
          onProgress: (int progress) {},
          onPageStarted: (String url) {},
          onPageFinished: (String url) {
            //页面加载完成之后才能执行JS
            _handleBackForbid();
          },
          onWebResourceError: (WebResourceError error) {},
          onNavigationRequest: (NavigationRequest request) {
            if (request.url.contains("web-view://communication")) {
              //协议好，然后可以获取从H5传递过来的数据
              Uri uri = Uri.parse(request.url);
              var value = uri.queryParameters['key'];
              return NavigationDecision.prevent; //不跳转
            }
            return NavigationDecision.navigate; //允许进行路由替换   跳转
          }))
      //加载一个URL,uri：可以通过Uri.parse(url)来将url转成uri
      ..loadRequest(Uri.parse(url!));
  }

  void _handleBackForbid() {
    // controller.runJavaScript(jsStr);
  }

  void flutterToH5() async {
    //调用下方方法之前需要 让h5页面加载完成之后进行，否则会报错
    var params = "";
    _controller.runJavaScript(
        "callH5Function('$params')"); //注意格式,callH5Function是h5那边定义的方法
    var params1 = "";
    var params2 = "";
    var result = await _controller.runJavaScriptReturningResult(
        "callH5Function2('$params1','$params2')"); //注意格式,callH5Function2是h5那边定义的方法
  }
}
